package com.vouov.util;

import com.google.appengine.repackaged.com.google.common.util.Base64;

import javax.crypto.Cipher;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.math.BigInteger;
import java.security.*;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Properties;

/**
 * User: yuminglong
 * Date: 11-11-18
 * Time: 下午2:54
 * Version: 1.0.0
 */
public class RSAUtils {
    /**
     * 生成密钥对
     * @return
     * @throws Exception
     */
    public static KeyPair generateKeyPair() throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(1024);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        return keyPair;
    }

    /**
     * 获取公钥
     * @param modulus
     * @param publicExponent
     * @return
     * @throws Exception
     */
    public static PublicKey getPublicKey(String modulus, String publicExponent) throws Exception {
        BigInteger myModulus = new BigInteger(modulus);
        BigInteger myPublicExponent = new BigInteger(publicExponent);
        RSAPublicKeySpec rsaPublicKeySpec = new RSAPublicKeySpec(myModulus, myPublicExponent);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePublic(rsaPublicKeySpec);
    }

    /**
     * 获取公钥
     * @param derPath
     * @return
     * @throws Exception
     */
    public static PublicKey getPublicKey(String derPath) throws Exception {
        File pubKeyFile = new File(derPath);
        DataInputStream dis = new DataInputStream(new FileInputStream(pubKeyFile));
        byte[] keyBytes = new byte[(int) pubKeyFile.length()];
        dis.readFully(keyBytes);
        dis.close();
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(keySpec);
        return publicKey;
    }

    /**
     * 获取密钥
     * @param modulus
     * @param privateExponent
     * @return
     * @throws Exception
     */
    public static PrivateKey getPrivateKey(String modulus, String privateExponent) throws Exception {
        BigInteger myModulus = new BigInteger(modulus);
        BigInteger myPrivateExponent = new BigInteger(privateExponent);
        RSAPrivateKeySpec rsaPrivateKeySpec = new RSAPrivateKeySpec(myModulus, myPrivateExponent);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(rsaPrivateKeySpec);
    }

    /**
     * 加密
     * @param key
     * @param message
     * @return
     * @throws Exception
     */
    public static String encrypt(Key key, String message) throws Exception{
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
        cipher.init(Cipher.ENCRYPT_MODE, key);
        cipher.update(message.getBytes("UTF-8"));
        return Base64.encode(cipher.doFinal());
    }

    /**
     *  解密
     * @param key
     * @param message
     * @return
     * @throws Exception
     */
    public static String decrypt(Key key, String message) throws Exception{
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
        cipher.init(Cipher.DECRYPT_MODE, key);
        cipher.update(Base64.decode(message));
        return new String(cipher.doFinal(), "UTF-8");
    }


    public void testRSA() throws Exception {
        String path = "E:/RSA/";
        KeyPair keyPair = generateKeyPair();
        File file = new File(path);
        File file1 = new File(file, "RSA.txt");
        File file2  = new File(file, "key.dat");
        Properties properties2 = new Properties();
        properties2.load(new FileInputStream(file2));
        PrivateKey privateKey = getPrivateKey(properties2.getProperty("modulus"), properties2.getProperty("private_exponent"));
        PublicKey publicKey = getPublicKey(properties2.getProperty("modulus"), properties2.getProperty("public_exponent"));
        Properties properties = new Properties();
        String text = "亚信联创（成都）有限公司 - Asiainfo linkage";
        System.out.println(text);
        System.out.println("**************************************************");
        RSAPublicKey publicKey2 = (RSAPublicKey) keyPair.getPublic();
        String encrypt = encrypt(publicKey2, text);
        System.out.println(encrypt);
        System.out.println("**************************************************");
        System.out.println(publicKey2.getModulus().toString());
        System.out.println("**************************************************");
        String encrypt2 = encrypt(publicKey, text);
        System.out.println(encrypt2);
        System.out.println("**************************************************");
        System.out.println(((RSAPublicKey)publicKey).getModulus().toString());
        System.out.println("**************************************************");
        String decrypt = decrypt(privateKey,encrypt);
        System.out.println(decrypt);
        System.out.println("**************************************************");
        String decrypt2 = decrypt(privateKey,encrypt2);
        System.out.println(decrypt);
    }

    public void testKeystore() throws Exception {
        String password = "admin123";
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        ks.load(this.getClass().getResourceAsStream("/com/vouov/security/test/testkeystore"), password.toCharArray());
        Key key = ks.getKey("test", password.toCharArray());

        System.out.println(key.getEncoded().length);
    }
}
